package com.mz.mattress.client.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mz.mattress.api.redis.RedisKeys;
import com.mz.mattress.api.common.Result;
import com.mz.mattress.api.entity.*;
import com.mz.mattress.api.enums.OrderStatusEnum;
import com.mz.mattress.api.enums.OrderTagEnum;
import com.mz.mattress.api.enums.UseOrderStatusEnum;
import com.mz.mattress.api.redis.RedisLock;
import com.mz.mattress.api.req.PrepayWxReq;
import com.mz.mattress.api.util.*;
import com.mz.mattress.client.api.req.SubmitOrderReq;
import com.mz.mattress.client.api.req.UseOrderReq;
import com.mz.mattress.client.api.resp.SubmitOrderResp;
import com.mz.mattress.client.common.FailMessage;
import com.mz.mattress.client.interceptor.GlobalExecutor;
import com.mz.mattress.client.mapper.*;
import com.mz.mattress.client.service.CardService;
import com.mz.mattress.client.service.MattressMsgService;
import com.mz.mattress.client.service.OrderService;
import com.mz.mattress.client.service.OrderUseTimesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.mz.mattress.client.service.OrderUseTimesService.DURATION;

@Slf4j
@Service
public class OrderServiceImpl extends AbstractPayService implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    protected MemberCouponMapper memberCouponMapper;

    @Autowired
    private OrderUseTimesMapper orderUseTimesMapper;

    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private RedisLock redisLock;

    @Autowired
    private MattressMsgService mattressMsgService;

    @Autowired
    private OrderUseTimesService orderUseTimesService;

    @Autowired
    private CardService cardService;

    @Override
    public Result<IPage<Order>> useListPage(Long memberId, Integer pageNo, Integer pageSize) {
        Page page = new Page(pageNo, pageSize);
        Page<Order> listPage = orderMapper.useListPage(page, memberId);
        return Result.ok(listPage);
    }

    @Override
    public Result<IPage<Order>> listPage(Long memberId, Integer status, Integer pageNo, Integer pageSize) {
        Page page = new Page(pageNo, pageSize);
        Page<Order> listPage = orderMapper.listPage(page, memberId);
        return Result.ok(listPage);
    }

    @Override
    public Result<List<Order>> list(Long memberId) {
        List<Order> list = orderMapper.list(memberId);
        return Result.ok(list);
    }

    @Override
    public Result<SubmitOrderResp> submit(SubmitOrderReq req) {

        Long memberId = req.getMemberId();

        Member member = memberMapper.selectById(memberId);
        if (member == null) {
            return Result.fail("找不到用户");
        }

        Integer goodsId = req.getGoodsId();
        Goods goods = goodsMapper.selectById(goodsId);
        Integer money = goods.getPrice();

        Integer couponId = req.getCouponId();
        Integer minus = 0;
        MemberCoupon memberCoupon = null;
        if (couponId != null) {
            memberCoupon = memberCouponMapper.selectById(couponId);
            if (memberCoupon == null || memberCoupon.getStatus() != 0) {
                return Result.fail("优惠券错误");
            }
            Integer discount = memberCoupon.getDiscount();
            if (discount == 0) {
                //是满减券
                if (money < memberCoupon.getFullMoney()) {
                    return Result.fail("优惠券未达到满减条件");
                }
                minus = memberCoupon.getMinusMoney();
                money -= minus;

            } else {
                //是打折券
                int after = money * discount / 100;
                minus = money - after;
                money = after;
            }
        }

        Long orderId = IdUtil.generatedCommonId(OrderTagEnum.mattressOrder);
        Order order = new Order();
        order.setOrderId(orderId);
        order.setTotalMoney(goods.getPrice());
        order.setCouponId(couponId);
        order.setMemberId(memberId);
        order.setMobile(member.getMobile());
        order.setCouponMoney(minus);
        order.setMoney(money);
        order.setGoodsId(goods.getId());
        order.setTitle(goods.getTitle());
        order.setCount(goods.getCount());
        order.setRemain(goods.getCount());
        order.setStatus(OrderStatusEnum.INIT.getValue());

        //每次消费金额
//        Integer perMoney = MathUtil.divide(order.getMoney(), order.getCount());
//        order.setPerMoney(perMoney);
        orderMapper.insert(order);

        //标记优惠券已使用
        if (memberCoupon != null) {
            MemberCoupon update = new MemberCoupon();
            update.setId(memberCoupon.getId());
            update.setUsedTime(DateUtil.getNowDateTime());
            update.setStatus(1);
            update.setUseOrderId(orderId);
            memberCouponMapper.updateById(update);
        }

        //返回 订单号 和 应付订单金额
        SubmitOrderResp submitOrderResp = new SubmitOrderResp();
        submitOrderResp.setOrderId(orderId.toString());
        submitOrderResp.setMoney(money);
        return Result.ok(submitOrderResp);

    }

    @Override
    public Result<Order> detail(Long orderId) {
        Order order = orderMapper.selectByOrderId(orderId);
        return Result.ok(order);
    }

    @Override
    public Result bindDevice(UseOrderReq req) {

        Long orderId = req.getOrderId();
        String deviceCode = req.getDeviceCode();
        Long memberId = req.getMemberId();
        if (orderId == null) {
            return Result.fail("参数错误");
        }

        String orderKey = RedisKeys.getOrderKey(orderId.toString());
        // 最多持有锁5秒
        Boolean isLock = redisLock.tryLock(orderKey, REQUEST_ID, 5, TimeUnit.SECONDS);
        if (!isLock) {
            log.warn("get_order_use_key_fail," + orderKey);
            return Result.fail("请稍后再试");
        }

        try {

            //扫了同一台设备的二维码， 找到未结束的订单
            OrderUseTimes times = orderUseTimesMapper.selectOneByMemberIdDeviceCode(memberId, deviceCode);
            if (times != null && times.getStatus() != UseOrderStatusEnum.DONE.getValue()) {
                return Result.ok(times.getId());
            }

            Device device = deviceMapper.selectByDeviceCode(deviceCode);
            if (device == null) {
                return Result.fail("找不到设备");
            }

            //检查当前设备是否有在执行订单
            if (device.getTimesId() != null && device.getTimesId() > 0) {

                //检查前一次订单是否在使用中
                OrderUseTimes one = orderUseTimesMapper.selectById(device.getTimesId());
                if (one != null) {
                    LocalDateTime dateTime = DateUtil.parseLocalDateTime(one.getCreateTime());
                    //上次订单 生成60分钟以内，并且是进行或暂停状态
                    if (LocalDateTime.now().isBefore(dateTime.plusMinutes(60))) {
                        if (one.getStatus() == UseOrderStatusEnum.DOING.getValue() ||
                                one.getStatus() == UseOrderStatusEnum.PAUSE.getValue()) {
                            return Result.fail("设备正在使用中");
                        }
                    }

                }
            }

            Order order = orderMapper.selectByOrderId(orderId);
            if (order == null || order.getStatus() < OrderStatusEnum.PAID.getValue()) {
                return Result.fail("订单错误");
            }

            if (order.getRemain() == 0) {
                return Result.fail("没有可用次数");
            }

            Member member = memberMapper.selectById(memberId);
            if (member == null) {
                return Result.fail("找不到会员信息");
            }

            //商家信息
            if (device.getMerchantId() != null && device.getMerchantId() > 0) {
                Merchant merchant = merchantMapper.selectById(device.getMerchantId());
                if (merchant == null) {
                    return Result.fail("找不到商家");
                }
            }

            //扣减使用次数  标记已消费
            Integer count = orderMapper.updateRemain(order.getId(), 1, device.getMerchantId(), order.getVersion());
            if (count == 0) {
                return Result.fail("请稍后重试");
            }

            Integer total = order.getCount();
            Integer remain = order.getRemain();
            //本次 分账金额
            Integer money = 0;
            boolean head = false;
            if (total == 1 && remain == 1 && order.getHeadMoney() == null) {
                //就一次 分账全部
                money = order.getMoney();
                head = true;
            } else if (total > 1) {
                // 说明是首次
                if (remain.equals(total) && order.getHeadMoney() == null) {
                    //首次 80%
                    money = MathUtil.discount(order.getMoney(), 80);
                    head = true;
                } else if (remain == 1 && order.getLastMoney() == null) {
                    //最后 20%
                    money = MathUtil.discount(order.getMoney(), 20);
                }
            }

            //订单记录分账金额
            if (money > 0) {
                Order update = new Order();
                update.setId(order.getId());
                if (head) {
                    update.setHeadMoney(money);
                } else {
                    update.setLastMoney(money);
                }
                orderMapper.updateById(update);
            }

            OrderUseTimes record = new OrderUseTimes();
            record.setOrderId(orderId);
            record.setProductKey(device.getProductKey());
            record.setDeviceName(device.getName());
            record.setDeviceCode(deviceCode);
            record.setDeviceId(device.getId());
            record.setMemberId(memberId);
            record.setMobile(member.getMobile());
            record.setSex(member.getSex());
            record.setBirthday(member.getBirthday());
            record.setWeight(member.getWeight());
            record.setMerchantId(device.getMerchantId());
            record.setMerchantName(device.getMerchantName());
            record.setGoodsName(order.getTitle());
            record.setRemain(order.getRemain() - 1);

            // 忽略演示设备
            if (req.getDev() == null || req.getDev() != 2) {
                //初始状态 0
                record.setStatus(UseOrderStatusEnum.INIT.getValue());
            } else {
                //是演示设备
                record.setStatus(UseOrderStatusEnum.DOING.getValue());
                record.setStartTime(DateUtil.getNowDateTime());
                record.setEndTime(DateUtil.plusMin(DURATION));
                record.setDuration(DURATION);
                record.setStart(1);
                record.setPlan(0);
            }

            //初始状态 0
//            record.setStatus(UseOrderStatusEnum.INIT.getValue());
            //本次分账金额
            record.setMoney(money);
//          record.setMoney(order.getPerMoney());
            //默认模式
            record.setMode(1);
//            record.setCity(merchant.getCity());
            record.setResults(0);
            orderUseTimesMapper.insert(record);

            // 忽略演示设备
//            if(device.getDemo()==null){
//                mattressMsgService.register(memberId, record);
//            }

            // 忽略演示设备
            if (req.getDev() == null || req.getDev() != 2) {
                mattressMsgService.register(memberId, record);
            }

            //异步发放佣金
            if (money > 0) {
                GlobalExecutor.executeBySingle(() -> {
                    orderUseTimesService.sendBonus(record.getId());
                });
            }

            Device update = new Device();
            update.setId(device.getId());
            update.setTemper(25);
            update.setVolume(3);
            update.setStrength(3);
            update.setWorkStatus(1);
            update.setTimesId(record.getId());
            deviceMapper.updateById(update);

            return Result.ok(record.getId());
        } catch (Exception e) {
            log.error("order_use_record_submit_error", e);
        } finally {
            redisLock.releaseLock(orderKey, REQUEST_ID);
        }

        return Result.fail();
    }

    @Override
    public Result cancel(Long orderId) {

        Order order = orderMapper.selectByOrderId(orderId);

        Order update = new Order();
        update.setId(order.getId());
        update.setStatus(OrderStatusEnum.CANCEL.getValue());
        orderMapper.updateById(update);

        if (order.getCouponId() != null) {
            //回退优惠券
            memberCouponMapper.backMemberCoupon(order.getCouponId());
        }

        return Result.ok();
    }


    @Override
    public Result beforePrepay(PrepayWxReq req) {

        Long orderId = Long.valueOf(req.getOrderId());

        Order order = orderMapper.selectByOrderId(orderId);
        if (order == null) {
            return Result.fail(FailMessage.ORDER_UNKNOWN);
        }
        //检查订单状态
        if (order.getStatus() != OrderStatusEnum.INIT.getValue()) {
            //订单不能支付
            return Result.fail(FailMessage.ORDER_PAY_FAIL);
        }

        req.setPayMoney(order.getMoney());

        return Result.ok();
    }

    @Override
    public boolean checkIsPaid(Long orderId) {
        Order order = orderMapper.selectByOrderId(orderId);
        if (order == null) {
            log.info("not_find_order,orderId=" + orderId);
            return false;
        }

        if (order.getStatus() > OrderStatusEnum.CANCEL.getValue()) {
            // 订单支付已做处理，去掉重复请求，保持接口面等
            log.info("order_has_paid,orderId=" + orderId);
            return true;
        }

        return false;
    }

    @Override
    public void doPaySuccess(Long orderId) {

        Order order = orderMapper.selectByOrderId(orderId);
        if (order == null) {
            return;
        }

        Order update = new Order();
        update.setId(order.getId());
        update.setPayMoney(order.getMoney());

        Integer perMoney = MathUtil.divide(order.getMoney(), order.getCount());
        update.setPerMoney(perMoney);

        //标记订单已支付
        update.setStatus(OrderStatusEnum.PAID.getValue());
        orderMapper.updateById(update);

        //累加会员订单总数
        memberMapper.incrementTotal(order.getMemberId());

        //发放卡项
        cardService.sendCard(order.getMemberId(), orderId.toString());

    }

    @Override
    public void doRefundSuccess(Long orderId, Integer money) {

        Order order = orderMapper.selectByOrderId(orderId);
        if (order == null) {
            return;
        }

        Order update = new Order();
        update.setId(order.getId());
        update.setRefund(money);
        update.setStatus(OrderStatusEnum.HAS_REFUND.getValue());
        orderMapper.updateById(update);

    }

    @Override
    public Result<Long> checkIsCanRefund(Long orderId, Integer money) {

        Order order = orderMapper.selectByOrderId(orderId);
        if (order == null) {
            return Result.fail(FailMessage.ORDER_UNKNOWN);
        }
        //检查订单状态
        if (order.getStatus() != OrderStatusEnum.PAID.getValue() &&
                order.getStatus() != OrderStatusEnum.HAS_CONSUME.getValue()) {
            return Result.fail("订单不能退款");
        }

//        if (money > order.getRemainMoney()) {
//            return Result.fail("退款金额超出可退金额");
//        }

        Long refundId = IdUtil.generatedCommonId(OrderTagEnum.mattressOrderRefund);

        return Result.ok(refundId);
    }


}
